package com.tiny.tinyweb.core.dao.xaccess;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;

import com.tiny.tinyweb.core.dao.entity.MapEntity;

/**
 * 基于{@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport}
 * 的JDBC操作基类，执行调用者指定的复杂SQL语句。
 * @param <T> 实体类的泛型约束
 * @see {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport}
 * @author wxiaobin
 */
public abstract class JdbcXAccess<T extends MapEntity> {
    /**
     * JDBC支持对象。
     */
    private NamedParameterJdbcDaoSupport jdbcDaoSupport;

    /**
     * 设置JDBC支持对象。
     * @param jdbcDaoSupport JDBC支持对象的值
     */
    public void setJdbcDaoSupport(NamedParameterJdbcDaoSupport jdbcDaoSupport) {
        this.jdbcDaoSupport = jdbcDaoSupport;
    }

    /**
     * 执行指定的SQL语句，将结果集映射到指定的实体对象，并返回实体对象列表。
     * @param sql 指定的SQL语句
     * @return entities 实体对象列表
     */
    @SuppressWarnings("unchecked")
    public List<T> jdbcRead(final String sql) {
        // 获得泛型的运行时类型，并创建运行时类型（具体的实体类）的实例
        Type[] args = ((ParameterizedType) this.getClass().getGenericSuperclass())
                .getActualTypeArguments();
        return (List<T>) this.jdbcDaoSupport.getNamedParameterJdbcTemplate().query(
                sql, new MapMapper<T>((Class<T>) args[0]));
    }

    /**
     * 执行指定的SQL语句，将结果集映射到指定的实体对象，并返回实体对象列表。
     * @param sql 指定的SQL语句
     * @param params SQL语句执行参数
     * @return entities 实体对象列表
     */
    @SuppressWarnings("unchecked")
    public List<T> jdbcRead(final String sql, final Map<String, Object> params) {
    	// 获得泛型的运行时类型，并创建运行时类型（具体的实体类）的实例
        Type[] args = ((ParameterizedType) this.getClass().getGenericSuperclass())
                .getActualTypeArguments();
        return (List<T>) this.jdbcDaoSupport.getNamedParameterJdbcTemplate().query(
                sql, params, new MapMapper<T>((Class<T>) args[0]));
    }

    /**
     * 执行更新语句，更新符合条件的记录的字段。
     * @param sql 表更新用SQL语句
     * @param params SQL语句执行参数（更新值和更新条件）
     * @return 受影响的记录行数
     */
    public int jdbcUpdate(final String sql, final Map<String, Object> params) {
        return this.jdbcDaoSupport.getNamedParameterJdbcTemplate().update(sql, params);
    }

    /**
     * 批量更新符合条件的记录的字段。
     * @param sql 表更新用SQL语句
     * @param params 一批SQL语句执行参数（更新值和更新条件）
     * @return 受影响的记录行数
     */
    public int[] jdbcBatchUpdate(final String sql, final Map<String, Object>[] params) {
        return this.jdbcDaoSupport.getNamedParameterJdbcTemplate().batchUpdate(sql, params);
    }
}
